home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / share / pygtk / 2.0 / codegen / scmexpr.py < prev    next >
Text File  |  2006-01-20  |  5KB  |  145 lines

  1. #!/usr/bin/env python
  2. # -*- Mode: Python; py-indent-offset: 4 -*-
  3. from __future__ import generators
  4.  
  5. import string
  6. import types
  7. from cStringIO import StringIO
  8.  
  9. class error(Exception):
  10.     def __init__(self, filename, lineno, msg):
  11.         Exception.__init__(self, msg)
  12.         self.filename = filename
  13.         self.lineno = lineno
  14.         self.msg = msg
  15.     def __str__(self):
  16.         return '%s:%d: error: %s' % (self.filename, self.lineno, self.msg)
  17.  
  18. trans = [' '] * 256
  19. for i in range(256):
  20.     if chr(i) in string.letters + string.digits + '_':
  21.         trans[i] = chr(i)
  22.     else:
  23.         trans[i] = '_'
  24. trans = string.join(trans, '')
  25.  
  26. def parse(filename):
  27.     if isinstance(filename, str):
  28.         fp = open(filename, 'r')
  29.     else: # if not string, assume it is some kind of iterator
  30.         fp = filename
  31.         filename = getattr(fp, 'name', '<unknown>')
  32.     whitespace = ' \t\n\r\x0b\x0c'
  33.     nonsymbol = whitespace + '();\'"'
  34.     stack = []
  35.     openlines = []
  36.     lineno = 0
  37.     for line in fp:
  38.         pos = 0
  39.         lineno += 1
  40.         while pos < len(line):
  41.             if line[pos] in whitespace: # ignore whitespace
  42.                 pass
  43.             elif line[pos] == ';': # comment
  44.                 break
  45.             elif line[pos:pos+2] == "'(":
  46.                 pass # the open parenthesis will be handled next iteration
  47.             elif line[pos] == '(':
  48.                 stack.append(())
  49.                 openlines.append(lineno)
  50.             elif line[pos] == ')':
  51.                 if len(stack) == 0:
  52.                     raise error(filename, lineno, 'close parenthesis found when none open')
  53.                 closed = stack[-1]
  54.                 del stack[-1]
  55.                 del openlines[-1]
  56.                 if stack:
  57.                     stack[-1] += (closed,)
  58.                 else:
  59.                     yield closed
  60.             elif line[pos] == '"': # quoted string
  61.                 if not stack:
  62.                     raise error(filename, lineno,
  63.                                 'string found outside of s-expression')
  64.                 endpos = pos + 1
  65.                 chars = []
  66.                 while endpos < len(line):
  67.                     if endpos+1 < len(line) and line[endpos] == '\\':
  68.                         endpos += 1
  69.                         if line[endpos] == 'n':
  70.                             chars.append('\n')
  71.                         elif line[endpos] == 'r':
  72.                             chars.append('\r')
  73.                         elif line[endpos] == 't':
  74.                             chars.append('\t')
  75.                         else:
  76.                             chars.append('\\')
  77.                             chars.append(line[endpos])
  78.                     elif line[endpos] == '"':
  79.                         break
  80.                     else:
  81.                         chars.append(line[endpos])
  82.                     endpos += 1
  83.                 if endpos >= len(line):
  84.                     raise error(filename, lineno, "unclosed quoted string")
  85.                 pos = endpos
  86.                 stack[-1] += (''.join(chars),)
  87.             else: # symbol/number
  88.                 if not stack:
  89.                     raise error(filename, lineno,
  90.                                 'identifier found outside of s-expression')
  91.                 endpos = pos
  92.                 while endpos < len(line) and line[endpos] not in nonsymbol:
  93.                     endpos += 1
  94.                 symbol = line[pos:endpos]
  95.                 pos = max(pos, endpos-1)
  96.                 try: symbol = int(symbol)
  97.                 except ValueError:
  98.                     try: symbol = float(symbol)
  99.                     except ValueError: pass
  100.                 stack[-1] += (symbol,)
  101.             pos += 1
  102.     if len(stack) != 0:
  103.         msg = '%d unclosed parentheses found at end of ' \
  104.               'file (opened on line(s) %s)' % (len(stack),
  105.                                                ', '.join(map(str, openlines)))
  106.         raise error(filename, lineno, msg)
  107.  
  108. class Parser:
  109.     def __init__(self, filename):
  110.         """Argument is either a string, a parse tree, or file object"""
  111.         self.filename = filename
  112.     def startParsing(self, filename=None):
  113.         statements = parse(filename or self.filename)
  114.         for statement in statements:
  115.             self.handle(statement)
  116.     def handle(self, tup):
  117.         cmd = string.translate(tup[0], trans)
  118.         if hasattr(self, cmd):
  119.             getattr(self, cmd)(*tup[1:])
  120.         else:
  121.             self.unknown(tup)
  122.     def unknown(self, tup):
  123.         pass
  124.  
  125. _testString = """; a scheme file
  126. (define-func gdk_font_load    ; a comment at end of line
  127.   GdkFont
  128.   ((string name)))
  129.  
  130. (define-boxed GdkEvent
  131.   gdk_event_copy
  132.   gdk_event_free
  133.   "sizeof(GdkEvent)")
  134. """
  135.  
  136. if __name__ == '__main__':
  137.     import sys
  138.     if sys.argv[1:]:
  139.         fp = open(sys.argv[1])
  140.     else:
  141.         fp = StringIO(_testString)
  142.     statements = parse(fp)
  143.     for s in statements:
  144.         print `s`
  145.